﻿<%
'''超级数组类
Class ListClass
	'允许抛出错误
	Public OverError
	'当前数组长度,Hash词典,Map词典,类内使用数组,是否忽略数组值大小写
	Private s_size, s_hash, s_map, s_list, s_comp
	
	'''构造
	Private Sub Class_Initialize()
		Set s_hash = Server.CreateObject(C_DicName)
		Set s_map  = Server.CreateObject(C_DicName)
		s_list = Array()
		s_size = 0
		OverError = True
		'Easp.Error(41) = "下标越界"
		'Easp.Error(42) = "下标不能为空"
		'Easp.Error(43) = "下标只能是数字、字母、下划线(_)、点(.)和斜杠(/)组成"
		'Easp.Error(44) = "参数必须是数组或者List对象"
		s_comp = 1
	End Sub
	
	'''析构
	Private Sub Class_Terminate()
		Set s_map  = Nothing
		Set s_hash = Nothing
	End Sub
	
	'''设置数组操作时是否忽略数组值的大小写
	'p_b:Bool值
	Public Property Let IgnoreCase(Byval p_b)
		s_comp = IIF(p_b, 1, 0)
	End Property
	
	'''查询数组操作时是否忽略数组值的大小写
	Public Property Get IgnoreCase()
		IgnoreCase = (s_comp = 1)
	End Property
	
	'''设置一个新的超级数组对象
	Public Function [New]()
		Set [New] = New ListClass
		[New].IgnoreCase = Me.IgnoreCase
	End Function
	
	'''返回当前数组的长度
	Public Property Get Size()
		Size = s_size
	End Property
	
	'''返回当前数组的长度,同Size
	Public Property Get Length()
		Length = s_size
	End Property
	
	'''返回数组的最大数字下标
	Public Property Get [End]()
		[End] = s_size - 1
	End Property
	
	'''设置值
	'p_a:值,可以是数组，也可以是以空格分隔的字符串
	'p_t:类型,0为简单数组;1为Hash数组
	Private Sub setData_(Byval p_a, Byval p_t)
		Dim t_a, t_i, t_j
		If IsArray(p_a) Then
			s_list = p_a
			s_size = Ubound(s_list) + 1
			If p_t = 0 Then
				Exit Sub
			End If
			For t_i = 0 To Ubound(p_a)
				If InStr(p_a(t_i),":")>0 Then
					t_j = CLeft(p_a(t_i),":")
					If Not s_map.Exists(t_j) Then
						s_map.Add t_i, t_j
						s_map.Add t_j, t_i
					End If
					p_a(t_i) = CRight(p_a(t_i),":")
				End If
			Next
			s_list = p_a
		Else
			t_a = Split(p_a, " ")
			s_list = t_a
			s_size = Ubound(s_list) + 1
			If p_t = 0 Then
				Exit Sub
			End If
			If InStr(p_a, ":")>0 Then
				For t_i = 0 To Ubound(t_a)
					If InStr(t_a(t_i),":")>0 Then
						t_j = CLeft(t_a(t_i),":")
						If Not s_map.Exists(t_j) Then
							s_map.Add t_i, t_j
							s_map.Add t_j, t_i
						End If
						t_a(t_i) = CRight(t_a(t_i),":")
					End If
				Next
			End If
			s_list = t_a
		End If
	End Sub
	
	'''设置源数组为简单数组并赋值
	Public Property Let Data(Byval p_a)
		setData_ p_a, 0
	End Property
	
	'''取出为普通数组
	Public Property Get Data()
		Data = s_list
	End Property
	
	'''设置源数组为Hash数组并赋值
	Public Property Let Hash(Byval p_a)
		setData_ p_a, 1
	End Property
	
	'''取出为普通数组，每个元素的值包含源Hash的列名和列值
	Public Property Get Hash()
		Dim t_a, t_i
		t_a = s_list
		For t_i = 0 To [End]
			If s_map.Exists(t_i) Then
				t_a(t_i) = s_map(t_i) & ":" & t_a(t_i)
			End If
		Next
		Hash = t_a
	End Property
		
	'''复制当前List对象为新的List对象而不影响当前对象
	Public Function Clone()
		Set Clone = Me.New
		Clone.Data = s_list
		If s_map.Count>0 Then
			Clone.Maps = s_map
		End If
	End Function
	
	'''将hash映射为Dictionary 对象
	'p_m:要存储的Dictionary 对象
	'p_h:要映射的hash的Dictionary 对象
	Private Sub cloneDic_(Byref p_m, Byref p_h)
		Dim t_i
		If p_m.Count > 0 Then
			p_m.RemoveAll
		End If
		For Each t_i In p_h
			p_m(t_i) = p_h(t_i)
		Next
	End Sub

	'''将Dictionary对象转化为Hash数组
	'p_d:Dictionary对象
	Public Property Let Maps(Byval p_d)
		If TypeName(p_d) = "Dictionary" Then
			cloneDic_ s_map, p_d
		End If
	End Property
	
	'''将Hash数组映射为 Dictionary 对象
	Public Property Get Maps()
		Set Maps = s_map
	End Property

	'''添加一个元素到数组的末尾
	Public Sub Push(Byval p_v)
		ReDim Preserve s_list(s_size)
		s_list(s_size) = p_v
		s_size = s_size + 1
	End Sub
	
	'''复制当前数组对象并添加一个元素到该数组的末尾
	Public Function CPush(Byval p_v)
		Set CPush = Me.Clone
		CPush.Push(p_v)
	End Function
	
	'''根据下标设置数组某一项的值
	'p_n:数组的下标，只能由自然数、字母、下划线(_)、点(.)和斜杠(/)组成
	'p_v:被设置的数组的值
	Public Property Let At(Byval p_n, Byval p_v)
		If IsN(p_n) Then
			Errc.Raise(42)
			Exit Property
		End If
		If VarType(p_n)=2 Or VarType(p_n)=3 Then
			If p_n > [End] Then
				ReDim Preserve s_list(p_n)
				s_size = p_n + 1
			End If
			s_list(p_n) = p_v
		ElseIf RegTest(p_n,"^[\w\./]+$") Then
			If Not s_map.Exists(p_n) Then
				s_map(p_n) = s_size
				s_map(s_size) = p_n
				Push(p_v)
			Else
				s_list(s_map(p_n)) = p_v
			End If
		Else
			Errc.Raise(43)
		End If
	End Property
	
	''''根据下标获取数组某一项的值,默认函数
	'p_n:数组的下标，只能由自然数、字母、下划线(_)、点(.)和斜杠(/)组成
	Public Default Property Get At(Byval p_n)
		If VarType(p_n)=2 Or VarType(p_n)=3 Then
			If p_n < s_size Then
				At = s_list(p_n)
			Else
				At = Null
				If OverError Then
					'Easp.Error.Msg = "(当前下标 " & p_n & " 超过了最大下标 " & [End] & " )"
					Errc.Raise(41)
				End If
			End If
		ElseIf RegTest(p_n,"^[\w-\./]+$") Then
			If s_map.Exists(p_n) Then
				At = s_list(s_map(p_n))
			Else
				At = Null
				If OverError Then
					'Easp.Error.Msg = "(当前列 " & p_n & " 不在数组Hash列中)"
					Errc.Raise(41)
				End If
			End If
		End If
	End Property
	
	'''返回数组的有效长度(非空值个数)
	Public Property Get Count()
		Dim t_i,t_j : t_j = 0
		For t_i = 0 To s_size-1
			If Has_s(At(t_i)) Then
				t_j = t_j + 1
			End If
		Next
		Count = t_j
	End Property
	
	'''返回数组第一个元素的值
	Public Property Get First()
		First = At(0)
	End Property
	
	'''返回数组最后一个元素的值
	Public Property Get Last()
		Last = At([End])
	End Property

	'''更新Map词典,键值p_i的值转为建p_n值
	'p_n:要更新的键值
	'p_i:要替换的键值
	Private Sub upFrom_(Byval p_n, Byval p_i)
		If p_n = p_i Then
			Exit Sub
		End If
		If s_map.Exists(p_i) Then
			s_map(s_map(p_i)) = p_n
			s_map(p_n) = s_map(p_i)
			s_map.Remove p_i
		End If
		At(p_n) = At(p_i)
	End Sub
	
	'''
	Private Function Compare__(Byval t, Byval a, Byval b)
		Dim isStr : isStr = False
		If VarType(a) = 8 Or VarType(b) = 8 Then
			isStr = True
			If IsNumeric(a) And IsNumeric(b) Then isStr = False
			If IsDate(a) And IsDate(b) Then isStr = False
		End If
		If isStr Then
			Select Case LCase(t)
				Case "lt" Compare__ = (StrComp(a,b,s_comp) = -1)
				Case "gt" Compare__ = (StrComp(a,b,s_comp) = 1)
				Case "eq" Compare__ = (StrComp(a,b,s_comp) = 0)
				Case "lte" Compare__ = (StrComp(a,b,s_comp) = -1 Or StrComp(a,b,s_comp) = 0)
				Case "gte" Compare__ = (StrComp(a,b,s_comp) = 1 Or StrComp(a,b,s_comp) = 0)
			End Select
		Else
			Select Case LCase(t)
				Case "lt" Compare__ = (a < b)
				Case "gt" Compare__ = (a > b)
				Case "eq" Compare__ = (a = b)
				Case "lte" Compare__ = (a <= b)
				Case "gte" Compare__ = (a >= b)
			End Select
		End If
	End Function
	
	'''向指定数字下标处插入一个或多个元素
	'p_n:数字下标
	'p_v:准备插入元素的内容
	Public Sub Insert(Byval p_n, Byval p_v)
		Dim t_i
		If p_n > [End] Then
			If IsArray(p_v) Then
				For t_i = 0 To UBound(p_v)
					At(p_n+t_i) = p_v(t_i)
				Next
			Else
				At(p_n) = p_v
			End If
		Else
			For t_i = s_size To (p_n+1) Step -1
				If IsArray(p_v) Then
					upFrom_ t_i+UBound(p_v), t_i-1
				Else
					upFrom_ t_i, t_i-1
				End If
			Next
			If IsArray(p_v) Then
				For t_i = 0 To UBound(p_v)
					At(p_n+t_i) = p_v(t_i)
				Next
			Else
				At(p_n) = p_v
			End If
		End If
	End Sub
	
	'''复制当前数组对象并向指定数字下标处插入一个或多个元素
	'p_n:数字下标
	'p_v:准备插入元素的内容
	Public Function CInsert(Byval p_n, Byval p_v)
		Set CInsert = Me.Clone
		CInsert.Insert p_n, p_v
	End Function

	Public Property Get Max()
		Dim i, v
		v = At(0)
		If s_size > 1 Then
			For i = 1 To [End]
				If Compare__("gt", At(i), v) Then v = At(i)
			Next
		End If
		Max = v
	End Property
	
	Public Property Get Min()
		Dim i, v
		v = At(0)
		If s_size > 1 Then
			For i = 1 To [End]
				If Compare__("lt", At(i), v) Then v = At(i)
			Next
		End If
		Min = v
	End Property
	
	Public Function NewArray(Byval a)
		Set NewArray = New ListClass
		NewArray.IgnoreCase = Me.IgnoreCase
		NewArray.Data = a
	End Function
	
	Public Function NewHash(Byval a)
		Set NewHash = New ListClass
		NewHash.IgnoreCase = Me.IgnoreCase
		NewHash.Hash = a
	End Function

	Public Property Get Serialize()
		Dim tmp, i : tmp = ""
		For i = 0 To [End]
			If s_map.Exists(i) Then
				tmp = tmp & "&" & s_map(i) & "=" & Server.URLEncode(At(i))
			End If
		Next
		If Len(tmp)>1 Then tmp = Mid(tmp,2)
		Serialize = tmp
	End Property
	
	Public Function HasIndex(Byval i)
		HasIndex = Index(i) >= 0
	End Function
	
	Public Function Index(Byval i)
		If isNumeric(i) Then
			Index = Easp.IIF(i >= 0 And i <= [End], i, -1)
		Else
			If s_map.Exists(i) Then
				Index = s_map(i)
			Else
				Index = -1
			End If
		End If
	End Function
	
	Public Function IndexHash(Byval i)
		If isNumeric(i) Then
			IndexHash = Easp.IfThen(s_map.Exists(i), s_map(i))
		Else
			IndexHash = Easp.IfThen(s_map.Exists(i), i)
		End If
	End Function

	Public Sub UnShift(Byval v)
		Insert 0, v
	End Sub
	
	Public Function UnShift_(Byval v)
		Set UnShift_ = Me.Clone
		UnShift_.UnShift v
	End Function
	
	Public Sub Shift()
		[Delete] 0
	End Sub
	
	Public Function Shift_()
		Set Shift_ = Me.Clone
		Shift_.Shift
	End Function
	
	Public Sub Pop()
		RemoveMap__ [End]
		ReDim Preserve s_list([End]-1)
		s_size = s_size - 1
	End Sub
	
	Public Function Pop_()
		Set Pop_ = Me.Clone
		Pop_.Pop
	End Function
	
	Private Sub RemoveMap__(Byval i)
		If s_map.Exists(i) Then
			s_map.Remove s_map(i)
			s_map.Remove i
		End If
	End Sub
	
	Public Function Has(Byval v)
		Has = (indexOf__(s_list, v) > -1)
	End Function
	
	Public Function IndexOf(Byval v)
		IndexOf = indexOf__(s_list, v)
	End Function
	
	Public Function IndexOfHash(Byval v)
		Dim i : i = indexOf__(s_list, v)
		If i = -1 Then IndexOfHash = Empty : Exit Function
		If s_map.Exists(i) Then
			IndexOfHash = s_map(i)
		Else
			IndexOfHash = Empty
		End If
	End Function
	
	Private Function indexOf__(Byval arr, Byval v)
		Dim i
		indexOf__ = -1
		For i = 0 To UBound(arr)
			If Compare__("eq", arr(i),v) Then
				indexOf__ = i
				Exit For
			End If
		Next
	End Function
	
	Public Sub [Delete](Byval n)
		Dim tmp,a,x,y,i
		If Instr(n, ",")>0 Or Instr(n,"-")>0 Then
			n = Replace(n,"\s","0")
			n = Replace(n,"\e",[End])
			a = Split(n, ",")
			For i = 0 To Ubound(a)
				If i>0 Then tmp = tmp & ","
				If Instr(a(i),"-")>0 Then
					x = Trim(Easp.CLeft(a(i),"-"))
					y = Trim(Easp.CRight(a(i),"-"))
					If Not Isnumeric(x) And s_map.Exists(x) Then x = s_map(x)
					If Not Isnumeric(y) And s_map.Exists(y) Then y = s_map(y)
					tmp = tmp & x & "-" & y
				Else
					x = Trim(a(i))
					If Not Isnumeric(x) And s_map.Exists(x) Then x = s_map(x)
					tmp = tmp & x
				End If
			Next
			a = Split(tmp,",")
			a = SortArray(a,0,UBound(a))
			tmp = "0-"
			For i = 0 To Ubound(a)
				If Instr(a(i),"-")>0 Then
					x = Easp.CLeft(a(i),"-")
					y = Easp.CRight(a(i),"-")
					tmp = tmp & x-1 & ","
					tmp = tmp & y+1 & "-"
				Else
					tmp = tmp & a(i)-1 & "," & a(i)+1 & "-"
				End If
			Next
			tmp = tmp & [End]
			Slice tmp
		Else
			If Not isNumeric(n) And s_map.Exists(n) Then
				n = s_map(n)
				RemoveMap__ n
			End If
			For i = n+1 To [End]
				upFrom_ i-1, i
			Next
			Pop
		End If
	End Sub
	
	Public Function Delete_(Byval n)
		Set Delete_ = Me.Clone
		Delete_.Delete n
	End Function
	
	Public Sub Uniq()
		Dim arr(),i,j : j = 0
		ReDim arr(-1)
		If s_hash.Count>0 Then s_hash.RemoveAll
		For i = 0 To [End]
			If indexOf__(arr, At(i)) = -1 Then
				ReDim Preserve arr(j)
				arr(j) = At(i)
				If s_map.Exists(i) Then
					s_hash.Add j, s_map(i)
					s_hash.Add s_map(i), j
				End If
				j = j + 1
			End If
		Next
		Data = arr
		cloneDic_ s_map, s_hash
		s_hash.RemoveAll
	End Sub
	
	Public Function Uniq_()
		Set Uniq_ = Me.Clone
		Uniq_.Uniq
	End Function
	
	Public Sub Rand()
		Dim i, j, tmp, Ei, Ej, Ti, Tj
		For i = 0 To [End]
			j = Easp.Rand(0,[End])
			Ei = s_map.Exists(i)
			Ej = s_map.Exists(j)
			If Ei Then Ti = s_map(i)
			If Ej Then Tj = s_map(j)
			tmp = At(j)
			At(j) = At(i)
			At(i) = tmp
			If Ei Then
				s_map(j) = Ti
				s_map(Ti) = j
			End If
			If Ej Then
				s_map(i) = Tj
				s_map(Tj) = i
			End If
			If Not (Ei And Ej) Then
				If Ei Then s_map.Remove i
				If Ej then s_map.Remove j
			End If
		Next
	End Sub
	
	Public Function Rand_()
		Set Rand_ = Me.Clone
		Rand_.Rand
	End Function
	
	Public Sub Reverse()
		Dim arr(),i,j : j = 0
		ReDim arr([End])
		If s_hash.Count>0 Then s_hash.RemoveAll
		For i = [End] To 0 Step -1
			arr(j) = At(i)
			If s_map.Exists(i) Then
				s_hash.Add j, s_map(i)
				s_hash.Add s_map(i), j
			End If
			j = j + 1
		Next
		Data = arr
		cloneDic_ s_map, s_hash
		s_hash.RemoveAll
	End Sub
	
	Public Function Reverse_()
		Set Reverse_ = Me.Clone
		Reverse_.Reverse
	End Function
	
	Public Sub Search(Byval s)
		Search__ s, True
	End Sub
	
	Public Function Search_(Byval s)
		Set Search_ = Me.Clone
		Search_.Search s
	End Function
	
	Public Sub SearchNot(Byval s)
		Search__ s, False
	End Sub
	
	Public Function SearchNot_(Byval s)
		Set SearchNot_ = Me.Clone
		SearchNot_.SearchNot s
	End Function
	
	Private Sub Search__(Byval s, Byval keep)
		Dim arr,i,tmp
		arr = Filter(s_list, s, keep, s_comp)
		If s_map.Count = 0 Then
			Data = arr
		Else
			AddHash__ arr
		End If
	End Sub
	
	Public Sub Compact()
		Dim arr(), i, j : j = 0
		If s_hash.Count>0 Then s_hash.RemoveAll
		For i = 0 To [End]
			If Easp.Has(At(i)) Then
				ReDim Preserve arr(j)
				arr(j) = At(i)
				If s_map.Exists(i) Then
					s_hash.Add j, s_map(i)
					s_hash.Add s_map(i), j
				End If
				j = j + 1
			End If
		Next
		Data = arr
		cloneDic_ s_map, s_hash
		s_hash.RemoveAll
	End Sub
	
	Public Function Compact_()
		Set Compact_ = Me.Clone
		Compact_.Compact
	End Function
	
	Public Sub Clear()
		s_list = Array()
		If s_map.Count>0 Then s_map.RemoveAll
		s_size = 0
	End Sub
	
	Public Sub Sort()
		Dim arr
		arr = s_list
		arr = SortArray(arr, 0, [End])
		If s_map.Count = 0 Then
			Data = arr
		Else
			AddHash__ arr
		End If
	End Sub
	
	Public Function Sort_()
		Set Sort_ = Me.Clone
		Sort_.Sort
	End Function
	
	Private Function SortArray(Byref arr, Byref low, Byref high)
		If Not IsArray(arr) Then Exit Function
		If Easp.IsN(arr) Then Exit Function
		Dim l, h, m, v, x
		l = low : h = high
		m = (low + high) \ 2 : v = arr(m)
		Do While (l <= h)
			Do While (Compare__("lt",arr(l),v) And l < high)
				l = l + 1
			Loop
			Do While (Compare__("lt",v,arr(h)) And h > low)
				h = h - 1
			Loop
			If l <= h Then
				x = arr(l) : arr(l) = arr(h) : arr(h) = x   
				l = l + 1 : h = h - 1         
			End If
		Loop
		If (low < h) Then arr = SortArray(arr, low, h)
		If (l < high) Then arr = SortArray(arr,l, high)
		SortArray = arr
	End Function
	
	Private Sub AddHash__(Byval arr)
		Dim tmp
		If s_hash.Count > 0 Then s_hash.RemoveAll
		For i = 0 To Ubound(arr)
			If IndexOfHash(arr(i))>"" Then
				tmp = IndexOfHash(arr(i))
				If Not s_hash.Exists(tmp) Then 
					s_hash.Add i, tmp
					s_hash.Add tmp, i
				End If
			End If
		Next
		Data = arr
		cloneDic_ s_map, s_hash
		s_hash.RemoveAll
	End Sub
	
	Public Sub Slice(Byval s)
		Dim a,i,j,k,x,y,arr
		If s_hash.Count>0 Then s_hash.RemoveAll
		s = Replace(s,"\s",0)
		s = Replace(s,"\e",[End])
		a = Split(s, ",")
		arr = Array() : k = 0
		For i = 0 To Ubound(a)
			If Instr(a(i),"-")>0 Then
				x = Trim(Easp.CLeft(a(i),"-"))
				y = Trim(Easp.CRight(a(i),"-"))
				If Not Isnumeric(x) And s_map.Exists(x) Then x = s_map(x)
				If Not Isnumeric(y) And s_map.Exists(y) Then y = s_map(y)
				x = Int(x) : y = Int(y)
				For j = x To y
					ReDim Preserve arr(k)
					arr(k) = At(j)
					If s_map.Exists(j) Then
						If Not s_hash.Exists(s_map(j)) Then
							s_hash.Add k, s_map(j)
							s_hash.Add s_map(j), k
						End If
					End If
					k = k + 1
				Next
			Else
				ReDim Preserve arr(k)
				x = Trim(a(i))
				If Not Isnumeric(x) And s_map.Exists(x) Then x = s_map(x)
				x = Int(x)
				If s_map.Exists(x) Then
					If Not s_hash.Exists(s_map(x)) Then
						s_hash.Add k, s_map(x)
						s_hash.Add s_map(x), k
					End If
				End If
				arr(k) = At(x)
				k = k + 1
			End If
		Next
		Data = arr
		cloneDic_ s_map, s_hash
		s_hash.RemoveAll
	End Sub
	
	Public Function Slice_(Byval s)
		Set Slice_ = Me.Clone
		Slice_.Slice s
	End Function
	
	Public Function [Get](Byval s)
		Set [Get] = Slice_(s)
	End Function
	
	Public Function J(Byval s)
		J = Join(s_list, s)
	End Function
	
	Public Function ToString()
		ToString = J(",")
	End Function
	
	Public Function ToArray()
		ToArray = s_list
	End Function
	
	Public Sub Map(Byval f)
		Map__ f, 0
	End Sub
	
	Public Function Map_(Byval f)
		Set Map_ = Me.Clone
		Map_.Map f
	End Function
	
	Public Sub [Each](Byval f)
		Map__ f, 1
	End Sub
	
	Private Sub Map__(Byval f, Byval t)
		Dim i, tmp
		For i = 0 To [End]
			tmp = Value__(At(i))
			If t = 0 Then
				At(i) = Eval(f & "("& tmp &")")
			ElseIf t = 1 Then
				ExecuteGlobal f & "("& tmp &")"
			End If
		Next
	End Sub
	
	Private Function Value__(Byval s)
		Dim tmp
		Select Case VarType(s)
			Case 7,8 tmp = """" & s & """"
			Case Else tmp = s
		End Select
		Value__ = tmp
	End Function
	
	Public Function Find(Byval f)
		Dim i, k, tmp
		k = "i"
		If Easp.Test(f,"[a-zA-Z]+:(.+)") Then
			k = Easp.CLeft(f,":")
			f = Easp.CRight(f,":")
		End If
		k = "%" & k
		For i = 0 To [End]
			tmp = Replace(Trim(f), k, Value__(At(i)))
			If Eval(tmp) Then
				Find = At(i) : Exit Function
			End If
		Next
		Find = Empty
	End Function
	
	Public Sub [Select](Byval f)
		Select__ f, 0
	End Sub
	
	Public Function Select_(Byval f)
		Set Select_ = Me.Clone
		Select_.Select f
	End Function
	
	Private Sub Select__(Byval f, Byval t)
		Dim i, j, k, tmp, arr
		arr = Array() : j = 0
		If s_hash.Count>0 Then s_hash.RemoveAll
		k = "i"
		If Easp.Test(f,"[a-zA-Z]+:(.+)") Then
			k = Easp.CLeft(f,":")
			f = Easp.CRight(f,":")
		End If
		k = "%" & k
		For i = 0 To [End]
			tmp = Replace(Trim(f), k, Value__(At(i)))
			If t = 0 Then
				tmp = Eval(tmp)
			ElseIf t = 1 Then
				tmp = (Not Eval(tmp))
			End If
			If tmp Then
				ReDim Preserve arr(j)
				arr(j) = At(i)
				If s_map.Exists(i) Then
					s_hash.Add j, s_map(i)
					s_hash.Add s_map(i), j
				End If
				j = j + 1
			End If
		Next
		Data = arr
		cloneDic_ s_map, s_hash
		s_hash.RemoveAll
	End Sub
	
	Public Sub Reject(Byval f)
		Select__ f, 1
	End Sub
	
	Public Function Reject_(Byval f)
		Set Reject_ = Me.Clone
		Reject_.Reject f
	End Function
	
	Public Sub Grep(Byval g)
		Dim i,j,arr
		arr = Array() : j = 0
		If s_hash.Count>0 Then s_hash.RemoveAll
		For i = 0 To [End]
			If Easp.Test(At(i),g) Then
				ReDim Preserve arr(j)
				arr(j) = At(i)
				If s_map.Exists(i) Then
					s_hash.Add j, s_map(i)
					s_hash.Add s_map(i), j
				End If
				j = j + 1
			End If
		Next
		Data = arr
		cloneDic_ s_map, s_hash
		s_hash.RemoveAll
	End Sub
	
	Public Function Grep_(Byval g)
		Set Grep_ = Me.Clone
		Grep_.Grep g
	End Function
	
	Public Sub SortBy(Byval f)
		Map f : Sort
	End Sub
	
	Public Function SortBy_(Byval f)
		Set SortBy_ = Me.Clone
		SortBy_.SortBy f
	End Function
	
	Public Sub Times(Byval t)
		Dim i, arr
		arr = s_list
		For i = 1 To t
			Insert s_size, arr
		Next
	End Sub
	
	Public Function Times_(Byval t)
		Set Times_ = Me.Clone
		Times_.Times t
	End Function
	
	Private Function IsList(Byval o)
		IsList = (Lcase(TypeName(o)) = "easyasp_list")
	End Function
	
	Public Sub Splice(Byval o)
		If Not isArray(o) And Not isList(o) Then Easp.Error.Raise 44 : Exit Sub
		Dim omap,dic,i
		If isArray(o) Then
			Insert s_size, o
		ElseIf IsList(o) Then
				Set omap = o.Maps
				If omap.Count > 0 Then
					For i = 0 To o.End
						If omap.Exists(i) And (Not s_map.Exists(omap(i))) Then
							s_map.Add s_size + i, omap(i)
							s_map.Add omap(i), s_size + i
						End If
					Next
				End If
				Insert s_size, o.Data
		End If
	End Sub
	
	Public Function Splice_(Byval o)
		Set Splice_ = Me.Clone
		Splice_.Splice o
	End Function
	
	Public Sub Merge(Byval o)
		Splice o
		Uniq
	End Sub
	
	Public Function Merge_(Byval o)
		Set Merge_ = Me.Clone
		Merge_.Merge o
	End Function
	
	Public Sub Inter(Byval o)
		If Not isArray(o) And Not isList(o) Then Easp.Error.Raise 44 : Exit Sub
		Dim i,j,k,omap,arr
		arr = Array() : j = 0
		If s_hash.Count>0 Then s_hash.RemoveAll
		If isArray(o) Then
			For i = 0 To Ubound(o)
				If Has(o(i)) Then
					ReDim Preserve arr(j)
					arr(j) = o(i)
					k = IndexOf(o(i))
					If s_map.Exists(k) Then
						s_hash.Add j, s_map(k)
						s_hash.Add s_map(k), j
					End If
					j = j + 1
				End If
			Next
		ElseIf IsList(o) Then
			Set omap = o.Maps
			For i = 0 To o.End
				If Has(o(i)) Then
					ReDim Preserve arr(j)
					arr(j) = o(i)
					k = IndexOf(o(i))
					If s_map.Exists(k) Then
						s_hash.Add j, s_map(k)
						s_hash.Add s_map(k), j
					ElseIf omap.Exists(i) Then
						s_hash.Add j, omap(i)
						s_hash.Add omap(i), j
					End If
					j = j + 1
				End If
			Next
		End If
		Data = arr
		cloneDic_ s_map, s_hash
		s_hash.RemoveAll
	End Sub
	
	Public Function Inter_(Byval o)
		Set Inter_ = Me.Clone
		Inter_.Inter o
	End Function
	
	Public Sub Diff(Byval o)
		If Not isArray(o) And Not isList(o) Then Easp.Error.Raise 44 : Exit Sub
		Dim i,j,arr,a
		arr = Array() : j = 0
		If s_hash.Count>0 Then s_hash.RemoveAll
		If isArray(o) Then
			a = o
			Set o = Me.New
			o.Data = a
		End If
		For i = 0 To [End]
			If Not o.Has(At(i)) Then
				ReDim Preserve arr(j)
				arr(j) = At(i)
				If s_map.Exists(i) Then
					s_hash.Add j, s_map(i)
					s_hash.Add s_map(i), j
				End If
				j = j + 1
			End If
		Next
		Data = arr
		cloneDic_ s_map, s_hash
		s_hash.RemoveAll
	End Sub
	
	Public Function Diff_(Byval o)
		Set Diff_ = Me.Clone
		Diff_.Diff o
	End Function
	
	Public Function Eq(Byval o)
		If Not isArray(o) And Not isList(o) Then Easp.Error.Raise 44 : Exit Function
		Dim a, e, m, i, j
		If isArray(o) Then
			a = o
			e = Ubound(a)
		ElseIf isList(o) Then
			a = o.Data
			e = o.End
		End If
		m = Easp.IIF([End] < e, [End], e)
		For i = 0 To m
			If Compare__("gt", At(i), a(i)) Then
				Eq = 1 : Exit Function
			ElseIf Compare__("lt", At(i), a(i)) Then
				Eq = -1 : Exit Function
			End If
		Next
		If [End] > e Then
			Eq = 1
		ElseIf [End] < e Then
			Eq = -1
		Else
			Eq = 0
		End If
	End Function
	
	Public Function Son(Byval o)
		If Not isArray(o) And Not isList(o) Then Easp.Error.Raise 44 : Exit Function
		Son = True
		Dim i
		If isList(o) Then o = o.Data
		For i = 0 To Ubound(o)
			If Not Has(o(i)) Then Son = False : Exit Function
		Next
	End Function
End Class
%>